package com.lumlord.common.log;

import java.lang.reflect.Method;
import java.util.Arrays;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lumlord.common.domain.Result;
import com.lumlord.service.LumlordLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.lumlord.common.annotation.Api;
import com.lumlord.common.base.ApiController;
import com.lumlord.common.exception.BusinessException;
import com.lumlord.common.spring.RequestJsonBody;
import com.lumlord.service.LumlordApiService;

/**
 * 操作日志记录处理
 * 
 * @author gpf
 * @date: 2018年9月10日 下午1:40:33
 */
@Aspect
@Component
@EnableAsync
public class LogAspect extends ApiController {

	// 配置织入点
	@Pointcut("@annotation(com.lumlord.common.annotation.Api)")
	public void logPointCut() {
	}

	/**
	 * 前置通知 用于拦截操作
	 *
	 * @param joinPoint 切点
	 */
	@AfterReturning(pointcut = "logPointCut()")
	public void doBefore(JoinPoint joinPoint) {
		getLog(joinPoint);
		handleLog(joinPoint, null);
	}

	/**
	 * 拦截异常操作
	 * 
	 * @param joinPoint
	 * @param e
	 */
	@AfterThrowing(value = "logPointCut()", throwing = "e")
	public void doAfter(JoinPoint joinPoint, Exception e) {
		handleLog(joinPoint, e);
	}
	
	
	@Async
	protected void handleLog(final JoinPoint joinPoint, final Exception e) {
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		if(null == requestAttributes){
			return;
		}

		HttpServletRequest request = requestAttributes.getRequest();
		HttpServletResponse response = requestAttributes.getResponse();

		try {

			if(null!=request.getParameter("parentUrl")){
				try{
					lumlordLogService.registerAction(request,response,request.getParameter("parentUrl"));
				}catch (BusinessException bus){
					Result.writeJson(response, Result.error(bus.getMessage()));
				}

			}

			// 获得注解
			Api controllerLog = getAnnotationLog(joinPoint);
			if (controllerLog == null) {
				return;
			}



			if(null != e ) {
				try{TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}catch (Exception ex){}
				if( e instanceof  BusinessException){
					lumlordLogService.instertSystemLog(request,response, LumlordLogService.SystemStatus.YWYC,e.getMessage());
				}else{
					lumlordLogService.instertSystemLog(request,response, LumlordLogService.SystemStatus.XTYC,e.getMessage());
				}
			}else if(controllerLog.isLog()){
				lumlordLogService.instertSystemLog(request,response, LumlordLogService.SystemStatus.ZC,"业务处理成功！");
			}

		} catch (Exception exp) {
			// 记录本地异常日志
			log.info("==前置通知异常==");
			log.info("异常信息:{}", exp.getMessage());
			exp.printStackTrace();
		}
	}

	public void getLog(JoinPoint joinPoint) {
		if(!aopLog) {
			return;
		}
		
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		if(null==requestAttributes){
			return;
		}
		HttpServletRequest request = requestAttributes.getRequest();
		// 打印请求内容
		log.info("===============请求内容===============");
		log.info("请求地址:" + request.getRequestURL().toString() + "请求方式:" + request.getMethod());
		log.info("请求类方法:" + joinPoint.getSignature());
		log.info("请求类方法参数:" + Arrays.toString(joinPoint.getArgs()));
		log.info(readRequestJson(request));
	}




	public String readRequestJson(HttpServletRequest request) {
		Object obj = request.getAttribute(RequestJsonBody.JSONBODY_ATTRIBUTE);
		return obj != null ? obj.toString() : null;
	}

	/**
	 * 是否存在注解，如果存在就获取
	 */

	Api getAnnotationLog(JoinPoint joinPoint) throws Exception {
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();

		if (method != null) {
			return method.getAnnotation(Api.class);
		}
		return null;
	}

	@Resource
	private LumlordApiService service;
	@Value("${lumlord.designer}")
	private String designer;
	@Value("${server.servlet.context-path}")
	private String serverName;
	@Value("${lumlord.log:false}")
	private boolean aopLog ;
	@Autowired
	private LumlordLogService lumlordLogService;
}
